package cn.org.itool.ws.framework.netty.auth;

import lombok.Data;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 认证对象信息
 *
 */
@Data
public class Principal {

    /**
     * 用户编号（用户唯一标识)
     */
    private final String id;

    /**
     * channel group name
     */
    private final String groupName;

    /**
     * principal unique identification
     */
    private final String mark;

    /**
     * 用户属性
     * key: tags - 用户tag
     */
    private final Map<String, Object> attrs;

    /**
     * 描述
     */
    private final String detail;

    /**
     * 构造{@link Principal}
     *
     * @param id         用户编号（用户唯一标识)
     * @param detail     描述
     * @param groupName channel group name
     */
    public Principal(String id, String groupName, String detail) {
        this(id, groupName, detail , Collections.emptyMap());
    }


    /**
     * 构造{@link Principal}
     *
     * @param id 用户编号（用户唯一标识)
     * @param detail 描述
     * @param attrs 属性
     */
    public Principal(String id, String groupName, String detail, Map<String, Object> attrs){
        this.id = id;
        this.groupName = groupName;
        this.mark = id + "_" + groupName;
        this.detail = detail;
        this.attrs = new ConcurrentHashMap<>(attrs);
    }

    /**
     * 获取属性值
     *
     * @param k 属性名
     * @return 属性值
     */
    public <T> Optional<T> getAttr(String k){
        return Optional.ofNullable((T)attrs.get(k));
    }

    public Object setAttr(String k, Object v){
        return attrs.put(k, v);
    }

    /**
     * 推入属性
     *
     * @param k 属性名
     * @param v 属性值
     * @return 属性存在返回替换值，属性不存在返回{@code null}
     */
    public Object put(String k, Object v){
        return attrs.put(k, v);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Principal principal = (Principal) o;
        return Objects.equals(mark, principal.mark);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mark);
    }
}
